package org.jspresso.framework.application.frontend.action;

import java.util.Map;

import org.jspresso.framework.action.ActionBusinessException;
import org.jspresso.framework.action.IActionHandler;
import org.jspresso.framework.binding.IValueConnector;
import org.jspresso.framework.model.component.IComponent;
import org.jspresso.framework.util.accessor.IAccessor;
import org.jspresso.framework.view.ICompositeView;
import org.jspresso.framework.view.IView;
import org.jspresso.framework.view.descriptor.IViewDescriptor;

public class SwitchModelForView<E, F, G> extends FrontendAction<E, F, G> {
	IViewDescriptor targetDescriptor;
	String			propertyUsed;

	@SuppressWarnings("unchecked")
	@Override
	public boolean execute(IActionHandler actionHandler, Map<String, Object> context) {

		IComponent selectedComponent = getSelectedModel(context);
		if(targetDescriptor != null && selectedComponent != null) {
			IView<E> view = findView((IView<E>)getView(context), targetDescriptor);
			Object connectorValue = null;

			if(propertyUsed == null) {
				connectorValue = selectedComponent;
			}
			else {
				IAccessor accessor = getController(context).getBackendController().getAccessorFactory().createPropertyAccessor(propertyUsed, selectedComponent.getComponentContract());
				try {
					connectorValue = accessor.getValue(selectedComponent);
				} catch (Exception e) {
					e.printStackTrace();
					throw new ActionBusinessException(e.getMessage() + " : See logs");
				}
			}
			IValueConnector componentConnector = getBackendController(context).createModelConnector(ACTION_MODEL_NAME, getBackendController(context).getEntityFactory().getComponentDescriptor(selectedComponent.getComponentContract()));
			componentConnector.setConnectorValue(null);
			getMvcBinder(context).bind(view.getConnector(), componentConnector);
			componentConnector.setConnectorValue(connectorValue);
			getMvcBinder(context).bind(view.getConnector(), componentConnector);

		}
		return super.execute(actionHandler, context);
	}

	private IView<E> findView(IView<E> currentView, IViewDescriptor descriptor) {
		return(findView(currentView, null, descriptor));
	}


	private IView<E> findView(IView<E> currentView, IView<E> ancestor, IViewDescriptor descriptor) {
		if(currentView.getDescriptor() == descriptor) {
			return currentView;
		}
		else if(currentView instanceof ICompositeView && ((ICompositeView<E>) currentView).getChildren() != null) {
			IView<E> foundView = null;
			for(IView<E> subView : ((ICompositeView<E>) currentView).getChildren()) {
				IView<E> currFound = findView(subView, currentView, descriptor);
				if(currFound != null) {
					foundView = currFound;
					break;
				}
			}
			if(foundView != null) {
				return foundView;
			}
		}
		if(currentView.getParent() != null && currentView.getParent() != ancestor) {
			return findView(currentView.getParent(), currentView, descriptor);
		}
		return null;
	}

	public void setTargetDescriptor(IViewDescriptor targetDescriptor) {
		this.targetDescriptor = targetDescriptor;
	}

	public void setPropertyUsed(String propertyUsed) {
		this.propertyUsed = propertyUsed;
	}



}
